#ifndef __CANOPEN_TYPES_H
#define __CANOPEN_TYPES_H

#include "stm32f4xx.h"
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

#define SDO_Wr1 0x2F
#define SDO_Wr2 0x2B
#define SDO_Wr3 0x27
#define SDO_Wr4 0x23

#pragma pack(push)
#pragma pack(1)

/* 主站向从站请求SDO，对于从站来说是接收，ID是0x600+ID */
typedef union{
    struct{
        uint8_t CS;
        uint16_t index;
        uint8_t sub_index;
        uint32_t data;
    }st_;
    uint8_t buf[8];
}SDOTx_T;

#pragma pack(pop)

typedef enum{
    SDO_IDLE = 0,       //变量初始化
    SDO_SENDING,
    SDO_WAIT_ACK,
    SDO_ERR,            //收到异常回复CS!=0x60
    SDO_GET_ACK,
    SDO_WAIT_NMT,       //SDO配置完成，等待nmt启动节点
    SDO_FINISH
}SDOState_T;

typedef struct{
    SDOState_T state;
    uint8_t ptr;   //当前需要发送的SDO索引
}SDOManager_T;


/**
   |   COB   |   CAN-ID      |
   +---------+---------------+
   |NMT      |   (000h)      |
   |SYNC     |   (080h)      |
   |TIME     |   (100h)      |
   |EMCY     |(081h)~(0FFh)  |
   |PDO1(tx) |(181h)~(1FFh)  |
   |PDO1(rx) |(201h)~(27Fh)  |
   |PDO2(tx) |(281h)~(2FFh)  |
   |PDO2(rx) |(301h)~(37Fh)  |
   |PDO3(tx) |(381h)~(3FFh)  |
   |PDO3(rx) |(401h)~(47Fh)  |
   |PDO4(tx) |(481h)~(4FFh)  |
   |PDO4(rx) |(501h)~(57Fh)  |
   |SDO(tx)  |(581h)~(5FFh)  |
   |SDO(rx)  |(601h)~(67Fh)  |
   +---------+---------------+
   |NMT      |               |
   |error    |(701h)~(77Fh)  |
   |control  |               |
   +---------+---------------+
*/
typedef enum{
    CO_NMT = 0,
    CO_SYNC = 1,
    CO_TIME,
    CO_EMCY,
    CO_TPDO1,
    CO_RPDO1,
    CO_TPDO2,
    CO_RPDO2,
    CO_TPDO3,
    CO_RPDO3,
    CO_TPDO4,
    CO_RPDO5,
    CO_TSDO,
    CO_RSDO,
    CO_HEARTBEAT
}CanOpenId_T;

typedef struct{
    uint8_t id;     //节点Id
    uint8_t state;  //状态 0-Bootup, 4-Stopped, 5-Operational, 127-Pre-Operational, 0xFF变量初始化的值
    CanOpenId_T id_type;  //最近从该节点收到消息的类型
    SDOManager_T manager;
}CanNodeInfo_T;

#define CAN_OK 0
#define CAN_FAIL 1

/* NMT error Control State */
#define NMTEC_BOOTUP          0
#define NMTEC_STOPPED         4
#define NMTEC_OPERATIONAL     5
#define NMTEC_PRE_OPERATION   127

/* NMT CS */
#define NMT_START             1
#define NMT_STOP              2
#define NMT_ENTER_PRE_OPERA   128
#define NMT_RESET_NODE        129
#define NMT_RESET_COMM        130

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
